#include <cmath>
#include <iostream>
#include <vector>
using namespace std;
#include "SysYIRGenerator.h"
#include "SysYParser.h"

namespace sysy
{
    [[noreturn]] void unimplemented(const std::string &s)
    {
        cerr << "unimplemented: " << s << "\n";
        exit(-1);
    }

    [[noreturn]] void semantic_error(const std::string &s)
    {
        cerr << "[语义错误]: " << s << '\n';
        exit(-1);
    }

    std::any sysy::SysYIRGenerator::visitCompUnit(SysYParser::CompUnitContext *ctx)
    {
        auto pModule = new Module();
        module.reset(pModule);

        auto getint_ty = Type::getFunctionType(Type::getIntType(32));
        auto getint_v = module->createFunction("getint", getint_ty, true);
        scope.insert(getint_ty, getint_v, true, "getint", "getint");

        auto getch_ty = Type::getFunctionType(Type::getIntType(32));
        auto getch_v = pModule->createFunction("getch", getint_ty, true);
        scope.insert(getch_ty, getch_v, true, "getch", "getch");

        auto getfloat_ty = Type::getFunctionType(Type::getFloatType());
        auto getfloat_v = pModule->createFunction("getfloat", getfloat_ty, true);
        scope.insert(getfloat_ty, getfloat_v, true, "getfloat", "getfloat");

        auto getarray_ty = Type::getFunctionType(Type::getIntType(32), {Type::getPointerType(Type::getIntType(32))});
        auto getarray_v = pModule->createFunction("getarray", getarray_ty, true);
        scope.insert(getarray_ty, getarray_v, true, "getarray", "getarray");

        auto getfarray_ty = Type::getFunctionType(Type::getIntType(32), {Type::getPointerType(Type::getFloatType())});
        auto getfarray_v = pModule->createFunction("getfarray", getfarray_ty, true);
        scope.insert(getfarray_ty, getfarray_v, true, "getfarray", "getfarray");

        auto putint_ty = Type::getFunctionType(Type::getVoidType(), {Type::getIntType(32)});
        auto putint_v = pModule->createFunction("putint", putint_ty, true);
        scope.insert(putint_ty, putint_v, true, "putint", "putint");

        auto putch_ty = Type::getFunctionType(Type::getVoidType(), {Type::getIntType(32)});
        auto putch_v = pModule->createFunction("putch", putch_ty, true);
        scope.insert(putch_ty, putch_v, true, "putch", "putch");

        auto putfloat_ty = Type::getFunctionType(Type::getVoidType(), {Type::getFloatType()});
        auto putfloat_v = pModule->createFunction("putfloat", putfloat_ty, true);
        scope.insert(putfloat_ty, putfloat_v, true, "putfloat", "putfloat");

        auto putarray_ty = Type::getFunctionType(Type::getVoidType(),
                                                 {Type::getIntType(32), Type::getPointerType(Type::getIntType(32))});
        auto putarray_v = pModule->createFunction("putarray", putarray_ty, true);
        scope.insert(putarray_ty, putarray_v, true, "putarray", "putarray");

        auto putfarray_ty = Type::getFunctionType(Type::getVoidType(),
                                                  {Type::getIntType(32), Type::getPointerType(Type::getFloatType())});
        auto putfarray_v = pModule->createFunction("putfarray", putfarray_ty, true);
        scope.insert(putfarray_ty, putfarray_v, true, "putfarray", "putfarray");

        auto llvm_memset_i32_ty =
            Type::getFunctionType(Type::getVoidType(),
                                  {Type::getPointerType(Type::getIntType(32)), Type::getIntType(8),
                                   Type::getIntType(32), Type::getIntType(1)});
        auto llvm_memset_i32_v = pModule->createFunction("llvm.memset.p0.i32", llvm_memset_i32_ty, true);
        scope.insert(llvm_memset_i32_ty, llvm_memset_i32_v, true, "llvm.memset.p0.i32", "llvm.memset.p0.i32");

        auto starttime_ty = Type::getFunctionType(Type::getVoidType(), {Type::getIntType(32)});
        auto starttime_v = pModule->createFunction("_sysy_starttime", starttime_ty, true);
        scope.insert(starttime_ty, starttime_v, true, "_sysy_starttime", "_sysy_starttime");

        auto stoptime_ty = Type::getFunctionType(Type::getVoidType(), {Type::getIntType(32)});
        auto stoptime_v = pModule->createFunction("_sysy_stoptime", starttime_ty, true);
        scope.insert(stoptime_ty, stoptime_v, true, "_sysy_stoptime", "_sysy_stoptime");


        for (auto item : ctx->compUnitItem())
        {
            item->accept(this);
        }
        return pModule;
    }

    std::any SysYIRGenerator::visitBType(SysYParser::BTypeContext *ctx)
    {
        auto ty_name = ctx->getText();
        return (ty_name == "int") ? Type::getIntType(32) : Type::getFloatType();
    }

    std::any SysYIRGenerator::visitBlock(SysYParser::BlockContext *ctx)
    {
        scope.pushLayer();
        for (auto item : ctx->blockItem())
        {
            item->accept(this);
            if (builder.unreachableBelow)
            {
                // builder.unreachableBelow = false;
                break;
            }
        }
        scope.popLayer();
        return builder.getBasicBlock();
    }

    std::any SysYIRGenerator::visitBlockItem(SysYParser::BlockItemContext *ctx)
    {
        return ctx->decl() ? ctx->decl()->accept(this) : ctx->stmt()->accept(this);
    }

    std::any SysYIRGenerator::visitDecl(SysYParser::DeclContext *ctx)
    {
        bool isConst = ctx->Const() != nullptr;
        bool isGlobal = scope.isGlobal();
        auto type = any_cast<Type *>(ctx->bType()->accept(this));
        vector<Value *> values;

        for (auto varDef : ctx->varDef())
        {
            auto name = varDef->Ident()->getText();
            auto reg_Name = new_reg_name();
            //        auto           name = new_reg_name();
            vector<Value *> dims;
            for (auto dim : varDef->constExp())
                dims.push_back(any_cast<Value *>(dim->accept(this)));
            auto hasInit = varDef->initVal();
            Value *init = nullptr;
            if (isGlobal)
            {
                if (dims.size() == 0)
                {
                    if (hasInit)
                        init = any_cast<Value *>(hasInit->accept(this));
                    auto cv = dynamic_cast<ConstantValue *>(init);
                    if (init && cv)
                    {
                        if (type->isInt() && cv->isFloat())
                        {
                            init = ConstantValue::get((int)cv->getFloat(), to_string((int)cv->getFloat()), 32);
                        }
                        else if (type->isFloat() && cv->isInt())
                        {
                            init = ConstantValue::get((float)cv->getInt(), to_string((float)cv->getInt()));
                        }
                    }
                    if (!init)
                    {
                        if (type->isInt())
                            init = ConstantValue::get((int)0, to_string((int)0), 32);
                        else
                            init = ConstantValue::get((float)1.0, to_hex((float)1.0));
                    }
                    auto gv = module->createGlobalValue(name, Type::getPointerType(type), dims, init, isConst);
                    scope.insert(gv->getType(), gv, isConst, name, reg_Name);
                    values.push_back(gv);
                }
                else
                {
                    // array
                    auto [rdims, size] = getRealDims(dims);
                    //                builder = rdims;
                    builder.arrayInfo.realDims = rdims;

                    // 此处init无实际意义, 仅用于标记该数组有初始值
                    init = hasInit != nullptr ? dims[0] : nullptr;
                    auto gv = module->createGlobalValue(name, Type::getPointerType(Type::getArrayType(type, rdims)),
                                                        dims, init, isConst, size);

                    if (hasInit)
                    {
                        builder.arrayInfo.currentOffsets = vector(builder.arrayInfo.realDims.size(), 0);
                        builder.arrayInfo.globalValue = gv;
                        builder.arrayInfo.isAlloca = false;

                        auto weight = vector<int>(builder.arrayInfo.realDims.size(), 1);
                        for (int i = weight.size() - 2; i >= 0; i--)
                        {
                            weight[i] = rdims[i + 1] * weight[i + 1];
                        }

                        builder.arrayInfo.onArray = true;

                        builder.arrayInfo.maxSize = rdims;
                        for (int i = rdims.size() - 2; i >= 0; i--)
                        {
                            builder.arrayInfo.maxSize[i] *= builder.arrayInfo.maxSize[i + 1];
                        }
                        builder.arrayInfo.pos = 0;
                        builder.arrayInfo.maxSizeLowerBound = -1;

                        hasInit->accept(this);
                        builder.arrayInfo.onArray = false;
                    }
                    scope.insert(gv->getType(), gv, isConst, name, reg_Name);
                    values.push_back(gv);
                }
            }
            else
            {
                // alloca
                auto [rdims, size] = getRealDims(dims);
                if (isConst)
                {
                    if (dims.empty())
                    {
                        ConstantValue *cv;
                        if (hasInit)
                        {
                            cv = dynamic_cast<ConstantValue *>(any_cast<sysy::Value *>(hasInit->accept(this)));
                        }
                        else
                        {
                            if (type->isInt())
                            {
                                cv = ConstantValue::get(0, "0", 32);
                            }
                            else
                            {
                                cv = ConstantValue::get(0.f, to_hex(0.0f));
                            }
                        }
                        scope.insert(cv->getType(), cv, true, name, reg_Name);
                        values.emplace_back(cv);
                        continue;
                    }
                    else
                    {
                        //                    unimplemented("const局部数组");
                    }
                }

                if (hasInit)
                {
                    if (dims.empty())
                    {
                        // scalar
                        auto alloca = builder.createAllocaInst(Type::getPointerType(type), dims, reg_Name, isConst);
                        init = any_cast<Value *>(hasInit->accept(this));
                        if (auto gv = dynamic_cast<ConstantValue *>(init))
                        {
                            if (type->isInt() && gv->isFloat())
                            {
                                init = ConstantValue::get((int)gv->getFloat(), to_string((int)gv->getFloat()), 32);
                            }
                            else if (type->isFloat() && gv->isInt())
                            {
                                init = ConstantValue::get((float)gv->getInt(), to_hex((float)gv->getInt()));
                            }
                        }
                        else if (type->isInt() && init->getType()->isFloat())
                            init = builder.createFtoIInst(init, new_reg_name());
                        else if (type->isFloat() && init->getType()->isInt())
                            init = builder.createIToFInst(init, new_reg_name());

                        auto store = builder.createStoreInst(init, alloca);
                        if (isConst)
                        {
                            auto cv = dynamic_cast<ConstantValue *>(init);
                            if (cv->isInt())
                                alloca->setInt(cv->getInt());
                            else
                                alloca->setFloat(cv->getFloat());
                        }
                        scope.insert(alloca->getType(), alloca, isConst, name, reg_Name);
                        values.push_back(alloca);
                    }
                    else
                    {
                        // TODO: 局部数组声明
                        // array

                        auto alloca = builder.createAllocaInst(Type::getPointerType(Type::getArrayType(type, rdims)),
                                                               dims, reg_Name, isConst, size);
                        //                builder = rdims;
                        builder.arrayInfo.realDims = rdims;

                        // 调用llvm内置memset设置全0
                        builder.createCallInst(dynamic_cast<Function *>(scope.find("llvm.memset.p0.i32")->value),
                                               {alloca, ConstantValue::get(0, "0", 8),
                                                ConstantValue::get(size * 4, to_string(size * 4), 32),
                                                ConstantValue::get(0, "0", 1)});

                        if (hasInit)
                        {
                            builder.arrayInfo.currentOffsets.assign(builder.arrayInfo.realDims.size(), 0);
                            builder.arrayInfo.allocaValue = alloca;
                            builder.arrayInfo.isAlloca = true;

                            auto weight = vector<int>(builder.arrayInfo.realDims.size(), 1);
                            for (int i = weight.size() - 2; i >= 0; i--)
                            {
                                weight[i] = rdims[i + 1] * weight[i + 1];
                            }

                            builder.arrayInfo.onArray = true;

                            builder.arrayInfo.maxSize = rdims;
                            for (int i = rdims.size() - 2; i >= 0; i--)
                            {
                                builder.arrayInfo.maxSize[i] *= builder.arrayInfo.maxSize[i + 1];
                            }
                            builder.arrayInfo.pos = 0;
                            builder.arrayInfo.maxSizeLowerBound = -1;

                            hasInit->accept(this);

                            builder.arrayInfo.onArray = false;
                        }
                        scope.insert(alloca->getType(), alloca, isConst, name, reg_Name);
                        values.push_back(alloca);
                    }
                }
                else
                {
                    if (dims.empty())
                    {
                        auto alloca = builder.createAllocaInst(Type::getPointerType(type), dims, reg_Name, isConst);
                        scope.insert(alloca->getType(), alloca, isConst, name, reg_Name);
                        values.emplace_back(alloca);
                    }
                    else
                    {
                        auto alloca = builder.createAllocaInst(Type::getPointerType(Type::getArrayType(type, rdims)),
                                                               dims, reg_Name, isConst);
                        scope.insert(alloca->getType(), alloca, isConst, name, reg_Name);
                        values.emplace_back(alloca);
                    }
                }
            }
        }

        return nullptr;
    }

    std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx)
    {
        auto name = ctx->Ident()->getText();
        vector<Type *> paramTypes;
        vector<string> paramNames;
        if (ctx->funcFParams())
        {
            auto params = ctx->funcFParams()->funcFParam();
            for (auto param : params)
            {
                auto ty = any_cast<Type *>(param->bType()->accept(this));
                if (param->EmptyArray())
                {
                    if (!param->exp().empty())
                    {
                        vector<int> rdims;
                        for (auto dim : param->exp())
                        {
                            rdims.emplace_back(
                                dynamic_cast<ConstantValue *>(any_cast<Value *>(dim->accept(this)))->getInt());
                        }
                        ty = Type::getArrayType(ty, rdims);
                    }

                    ty = Type::getPointerType(ty);
                }
                paramTypes.push_back(ty);
                paramNames.push_back(param->Ident()->getText());
            }
        }
        Type *returnType = any_cast<Type *>(ctx->funcType()->accept(this));
        auto funcType = Type::getFunctionType(returnType, paramTypes);
        auto function = module->createFunction(name, funcType);

        // 符号表中添加该函数
        // 函数是不可修改的
        scope.insert(funcType, function, true, name, name);

        auto entry = function->getEntryBlock();
        for (auto i = 0; i < paramTypes.size(); i++)
        {
            // TODO: 数组参数
            function->createArgument(paramTypes[i], new_reg_name());
        }
        // 为函数体提前分配一层符号表
        scope.pushLayer();
        scope.preEnter = true;
        builder.setPosition(entry, entry->end());
        // 添加参数
        for (auto i = 0; i < paramTypes.size(); i++)
        {
            // 很明显参数还没有值
            // 在栈上为参数分配空间, 将alloca的值放入符号表
            auto reg_Name = new_reg_name();
            auto alloca = builder.createAllocaInst(Type::getPointerType(paramTypes[i]), {}, reg_Name);
            scope.insert(paramTypes[i], alloca, false, paramNames[i], reg_Name);

            // 将实参的值存到分配的空间里
            builder.createStoreInst((Value *)&function->getArguments()[i], alloca);
        }

        // 添加返回值
        if (!returnType->isVoid())
            function->setRetValue(builder.createAllocaInst(Type::getPointerType(returnType), {}, new_reg_name()));
        auto funcExit = function->createFuncExitBlock();

        ctx->block()->accept(this);

        // 如果到此时funcexit块的前驱还是空的话, 证明该基本块没有成为跳转语句的目标, 因此没有存在的意义, 删掉即可
        // 否则, 余下的load/ret仍然构成一个单独的基本块
        if (funcExit->getPredecessors().empty())
            function->removeFuncExitBlock();
        else
        {
            function->keepFuncExitBlock();
            auto curr = builder.getBasicBlock();
            curr->getSuccessors().emplace_back(funcExit);
            funcExit->getPredecessors().emplace_back(curr);
        }
        builder.setPosition(function->getExitBlock(), function->getExitBlock()->end());

        // 添加return
        if (!returnType->isVoid())
        {
            auto retv = builder.createLoadInst(function->getRetValue(), new_reg_name());
            builder.createReturnInst(retv);
        }
        else
            builder.createReturnInst(nullptr);
        builder.unreachableBelow = false;
        return function;
    }

    // return ConstantValue
    std::any SysYIRGenerator::visitNumAsPri(SysYParser::NumAsPriContext *ctx)
    {
        if (ctx->number()->IntConst())
        {
            int base = 10;
            auto prefix = ctx->number()->IntConst()->getText().substr(0, 2);
            if (prefix == "0x" || prefix == "0X")
                base = 16;
            else if (prefix[0] == '0')
                base = 8;
            int v = stoi(ctx->number()->IntConst()->getText(), nullptr, base);
            return (Value *)ConstantValue::get(v, to_string(v), 32);
        }
        else
        {
            float v = stof(ctx->number()->FloatConst()->getText());
            return (Value *)ConstantValue::get(v, to_hex(v));
        }
    }

    std::any SysYIRGenerator::visitPriAsUna(SysYParser::PriAsUnaContext *ctx)
    {
        return ctx->primaryExp()->accept(this);
    }

    std::any SysYIRGenerator::visitUnaAsMul(SysYParser::UnaAsMulContext *ctx) { return ctx->unaryExp()->accept(this); }

    std::any SysYIRGenerator::visitMulAsAdd(SysYParser::MulAsAddContext *ctx) { return ctx->mulExp()->accept(this); }

    std::any SysYIRGenerator::visitExp(SysYParser::ExpContext *ctx)
    {
        if (ctx->String())
        {
            // 传字符串作为参数, 目前不考虑
            unimplemented("字符串作为表达式");
            return nullptr;
        }
        else
        {
            return ctx->addExp()->accept(this);
        }
    }

    std::any SysYIRGenerator::visitFuncType(SysYParser::FuncTypeContext *ctx)
    {
        auto name = ctx->getText();
        if (name == "int")
            return Type::getIntType(32);
        else if (name == "float")
            return Type::getFloatType();
        else
            return Type::getVoidType();
    }

    std::any SysYIRGenerator::visitRelAddAsRel(SysYParser::RelAddAsRelContext *ctx)
    {
        auto *RelTerm = any_cast<Value *>(ctx->relExp()->accept(this));
        auto *RelTerm_Constant = dynamic_cast<ConstantValue *>(RelTerm);
        auto *AddTerm = any_cast<Value *>(ctx->addExp()->accept(this));
        auto *AddTerm_Constant = dynamic_cast<ConstantValue *>(AddTerm);

        if (RelTerm_Constant && AddTerm_Constant)
        {
            if (RelTerm_Constant->isInt() && AddTerm_Constant->isInt())
            {
                int RelTerm_Value = RelTerm_Constant->getInt();
                int AddTerm_Value = AddTerm_Constant->getInt();

                if (ctx->relop->getText() == "<")
                {
                    int value = (RelTerm_Value < AddTerm_Value);
                    return (Value *)ConstantValue::get(value, to_string(value), 32);
                }
                else if (ctx->relop->getText() == ">")
                {
                    int value = (RelTerm_Value > AddTerm_Value);
                    return (Value *)ConstantValue::get(value, to_string(value), 32);
                }
                else if (ctx->relop->getText() == "<=")
                {
                    int value = (RelTerm_Value <= AddTerm_Value);
                    return (Value *)ConstantValue::get(value, to_string(value), 32);
                }
                else if (ctx->relop->getText() == ">=")
                {
                    int value = (RelTerm_Value >= AddTerm_Value);
                    return (Value *)ConstantValue::get(value, to_string(value), 32);
                }
            }
            else
            {
                float RelTerm_Value, AddTerm_Value;

                if (RelTerm_Constant->isInt())
                    RelTerm_Value = float(RelTerm_Constant->getInt());
                else
                    RelTerm_Value = RelTerm_Constant->getFloat();
                if (AddTerm_Constant->isInt())
                    AddTerm_Value = float(AddTerm_Constant->getInt());
                else
                    AddTerm_Value = AddTerm_Constant->getFloat();

                if (ctx->relop->getText() == "<")
                {
                    int value = (RelTerm_Value < AddTerm_Value);
                    return (Value *)ConstantValue::get(value, to_string(value), 32);
                }
                else if (ctx->relop->getText() == ">")
                {
                    int value = (RelTerm_Value > AddTerm_Value);
                    return (Value *)ConstantValue::get(value, to_string(value), 32);
                }
                else if (ctx->relop->getText() == "<=")
                {
                    int value = (RelTerm_Value <= AddTerm_Value);
                    return (Value *)ConstantValue::get(value, to_string(value), 32);
                }
                else if (ctx->relop->getText() == ">=")
                {
                    int value = (RelTerm_Value >= AddTerm_Value);
                    return (Value *)ConstantValue::get(value, to_string(value), 32);
                }
            }
        }
        else
        {
            // 转换会造成一定的损失，先判断是否含float，若不是，不需要转换
            if (!RelTerm->isFloat() && !AddTerm->isFloat())
            {
                if (ctx->relop->getText() == "<")
                {
                    return (Value *)builder.createICmpLTInst(RelTerm, AddTerm, new_reg_name());
                }
                else if (ctx->relop->getText() == ">")
                {
                    return (Value *)builder.createICmpGTInst(RelTerm, AddTerm, new_reg_name());
                }
                else if (ctx->relop->getText() == "<=")
                {
                    return (Value *)builder.createICmpLEInst(RelTerm, AddTerm, new_reg_name());
                }
                else if (ctx->relop->getText() == ">=")
                {
                    return (Value *)builder.createICmpGEInst(RelTerm, AddTerm, new_reg_name());
                }
            }
            else
            {
                if (RelTerm->isInt())
                {
                    if (RelTerm->isBool())
                        RelTerm = builder.createI1ToI32Inst(RelTerm, new_reg_name());
                    RelTerm = builder.createIToFInst(RelTerm, new_reg_name());
                }
                if (AddTerm->isInt())
                {
                    if (AddTerm->isBool())
                        AddTerm = builder.createI1ToI32Inst(AddTerm, new_reg_name());
                    AddTerm = builder.createIToFInst(AddTerm, new_reg_name());
                }

                if (ctx->relop->getText() == "<")
                {
                    return (Value *)builder.createFCmpLTInst(RelTerm, AddTerm, new_reg_name());
                }
                else if (ctx->relop->getText() == ">")
                {
                    return (Value *)builder.createFCmpGTInst(RelTerm, AddTerm, new_reg_name());
                }
                else if (ctx->relop->getText() == "<=")
                {
                    return (Value *)builder.createFCmpLEInst(RelTerm, AddTerm, new_reg_name());
                }
                else if (ctx->relop->getText() == ">=")
                {
                    return (Value *)builder.createFCmpGEInst(RelTerm, AddTerm, new_reg_name());
                }
            }
        }

        return (Value *)nullptr;
    }

    std::any SysYIRGenerator::visitAddAsRel(SysYParser::AddAsRelContext *ctx) { return ctx->addExp()->accept(this); }

    std::any SysYIRGenerator::visitEqRelAsEq(SysYParser::EqRelAsEqContext *ctx)
    {
        auto EqTerm = any_cast<Value *>(ctx->eqExp()->accept(this));
        auto EqTerm_Constant = dynamic_cast<ConstantValue *>(EqTerm);
        auto RelTerm = any_cast<Value *>(ctx->relExp()->accept(this));
        auto RelTerm_Constant = dynamic_cast<ConstantValue *>(RelTerm);

        // 原程序没有做是否为Constant的判断
        if (EqTerm_Constant && RelTerm_Constant)
        {
            if (EqTerm_Constant->isInt() && RelTerm_Constant->isInt())
            {
                int EqTerm_Value = EqTerm_Constant->getInt();
                int RelTerm_Value = RelTerm_Constant->getInt();

                if (ctx->eqop->getText() == "==")
                {
                    int value = (EqTerm_Value == RelTerm_Value);
                    return (Value *)ConstantValue::get(value, to_string(value), 32);
                }
                else if (ctx->eqop->getText() == "!=")
                {
                    int value = (EqTerm_Value != RelTerm_Value);
                    return (Value *)ConstantValue::get(value, to_string(value), 32);
                }
            }
            else
            {
                float EqTerm_Value, RelTerm_Value;

                if (EqTerm_Constant->isInt())
                    EqTerm_Value = float(EqTerm_Constant->getInt());
                else if (EqTerm_Constant->isFloat())
                    EqTerm_Value = EqTerm_Constant->getFloat();
                if (RelTerm_Constant->isInt())
                    RelTerm_Value = float(RelTerm_Constant->getInt());
                else if (RelTerm_Constant->isFloat())
                    RelTerm_Value = RelTerm_Constant->getFloat();

                if (ctx->eqop->getText() == "==")
                {
                    int value = (EqTerm_Value == RelTerm_Value);
                    return (Value *)ConstantValue::get(value, to_string(value), 32);
                }
                else if (ctx->eqop->getText() == "!=")
                {
                    int value = (EqTerm_Value != RelTerm_Value);
                    return (Value *)ConstantValue::get(value, to_string(value), 32);
                }
            }
        }
        else
        {
            if (!EqTerm->isFloat() && !RelTerm->isFloat())
            {
                if (EqTerm->isBool())
                {
                    EqTerm = builder.createI1ToI32Inst(EqTerm, new_reg_name());
                }
                if (RelTerm->isBool())
                {
                    RelTerm = builder.createI1ToI32Inst(RelTerm, new_reg_name());
                }
                if (ctx->eqop->getText() == "==")
                    return (Value *)builder.createICmpEQInst(EqTerm, RelTerm, new_reg_name());
                else if (ctx->eqop->getText() == "!=")
                    return (Value *)builder.createICmpNEInst(EqTerm, RelTerm, new_reg_name());
            }
            else
            {
                if (EqTerm->isInt())
                {
                    if (EqTerm->isBool())
                        EqTerm = builder.createI1ToI32Inst(EqTerm, new_reg_name());
                    EqTerm = builder.createIToFInst(EqTerm, new_reg_name());
                }
                if (RelTerm->isInt())
                {
                    if (RelTerm->isBool())
                        RelTerm = builder.createI1ToI32Inst(RelTerm, new_reg_name());
                    RelTerm = builder.createIToFInst(RelTerm, new_reg_name());
                }

                if (ctx->eqop->getText() == "==")
                    return (Value *)builder.createFCmpEQInst(EqTerm, RelTerm,
                                                             new_reg_name()); // 原程序没有new_reg_name()
                else if (ctx->eqop->getText() == "!=")
                    return (Value *)builder.createFCmpNEInst(EqTerm, RelTerm,
                                                             new_reg_name()); // 原程序没有new_reg_name()
            }
        }
        return (Value *)nullptr;
    }

    std::any SysYIRGenerator::visitRelAsEq(SysYParser::RelAsEqContext *ctx) { return ctx->relExp()->accept(this); }

    std::any SysYIRGenerator::visitLAndEqAsLAnd(SysYParser::LAndEqAsLAndContext *ctx)
    {
        auto *CurBlock = builder.getBasicBlock(); // 当前块
        auto *Func = CurBlock->getParent(); // 当前函数
        // scope.insert(NewName, (Value *)CurBlock);
        // //TODO:这里存在Phi函数（还没写）

        stringstream and_name;
        and_name << "and_" << builder.getIfNum();
        auto *NewBlock = Func->addBasicBlock(and_name.str()); // TODO:NewBlock里加了个字符表,这里存在Phi函数（还没写）
        trueExit.push(NewBlock);
        falseExit.push(falseExit.top());
        ctx->lAndExp()->accept(this);

        builder.setPosition(NewBlock, NewBlock->begin());
        auto *EqTerm = any_cast<Value *>(ctx->eqExp()->accept(this));
        auto Eqterm_Ins = dynamic_cast<Instruction *>(EqTerm);

        auto *Successors_Block = trueExit.top();
        auto *Predecessors_Block = falseExit.top();
        trueExit.pop();
        falseExit.pop();


        if (auto cv = dynamic_cast<ConstantValue *>(EqTerm); cv != nullptr)
        {
            bool cond;
            assert(cv->isInt() || cv->isFloat());
            if (cv->isFloat())
                cond = cv->getFloat() != 0.0;
            if (cv->isInt())
                cond = cv->getInt() != 0;
            if (cond)
            {
                auto ins = builder.createUncondBrInst(Successors_Block);
                if (ins != nullptr)
                {
                    NewBlock->getSuccessors().push_back(Successors_Block);
                    Successors_Block->getPredecessors().push_back(NewBlock);
                }
            }
            else
            {
                auto ins = builder.createUncondBrInst(Predecessors_Block);
                if (ins != nullptr)
                {
                    NewBlock->getSuccessors().push_back(Predecessors_Block);
                    Predecessors_Block->getPredecessors().push_back(NewBlock);
                }
            }
        }
        else
        {
            if (Eqterm_Ins && !dynamic_cast<Instruction *>(EqTerm)->isCmp())
            {
                // 如果为float，则重新构建一个与0.0比较的表达式
                if (EqTerm->isFloat())
                {
                    EqTerm = builder.createFCmpNEInst(EqTerm, ConstantValue::get(0.0f, to_hex(0.0)), new_reg_name());
                }
                else
                {
                    EqTerm = builder.createICmpNEInst(EqTerm, ConstantValue::get(0, "0", 32), new_reg_name());
                }
            }


            builder.createCondBrInst(EqTerm, Successors_Block, Predecessors_Block);

            NewBlock->getSuccessors().push_back(Successors_Block);
            Successors_Block->getPredecessors().push_back(NewBlock);
            NewBlock->getSuccessors().push_back(Predecessors_Block);
            Predecessors_Block->getPredecessors().push_back(NewBlock);
        }


        return (Value *)nullptr;
    }

    std::any SysYIRGenerator::visitEqAsLAnd(SysYParser::EqAsLAndContext *ctx)
    {
        auto *CurBlock = builder.getBasicBlock(); // 当前块

        auto *EqTerm = any_cast<Value *>(ctx->eqExp()->accept(this));
        auto Eqterm_Ins = dynamic_cast<Instruction *>(EqTerm);

        auto *Successors_Block = trueExit.top();
        auto *Predecessors_Block = falseExit.top();
        trueExit.pop();
        falseExit.pop();

        if (auto cv = dynamic_cast<ConstantValue *>(EqTerm); cv != nullptr)
        {
            bool cond;
            assert(cv->isInt() || cv->isFloat());
            if (cv->isFloat())
                cond = cv->getFloat() != 0.0;
            if (cv->isInt())
                cond = cv->getInt() != 0;
            if (cond)
            {
                auto ins = builder.createUncondBrInst(Successors_Block);
                if (ins != nullptr)
                {
                    CurBlock->getSuccessors().push_back(Successors_Block);
                    Successors_Block->getPredecessors().push_back(CurBlock);
                }
            }
            else
            {
                auto ins = builder.createUncondBrInst(Predecessors_Block);
                if (ins != nullptr)
                {
                    CurBlock->getSuccessors().push_back(Predecessors_Block);
                    Predecessors_Block->getPredecessors().push_back(CurBlock);
                }
            }
        }
        else
        {
            if (Eqterm_Ins && !Eqterm_Ins->isCmp())
            {
                // 如果为float，则重新构建一个与0.0比较的表达式
                if (EqTerm->isFloat())
                {
                    EqTerm = builder.createFCmpNEInst(EqTerm, ConstantValue::get(0.0f, to_hex(0.0)), new_reg_name());
                }
                else
                {
                    EqTerm = builder.createICmpNEInst(EqTerm, ConstantValue::get(0, "0", 32), new_reg_name());
                }
            }


            builder.createCondBrInst(EqTerm, Successors_Block, Predecessors_Block);
            CurBlock->getSuccessors().push_back(Successors_Block);
            Successors_Block->getPredecessors().push_back(CurBlock);
            CurBlock->getSuccessors().push_back(Predecessors_Block);
            Predecessors_Block->getPredecessors().push_back(CurBlock);
        }


        return (Value *)nullptr;
    }

    std::any SysYIRGenerator::visitOpUnaAsUna(SysYParser::OpUnaAsUnaContext *ctx)
    {
        auto unaryValue = any_cast<Value *>(ctx->unaryExp()->accept(this));
        auto constUnaryValue = dynamic_cast<ConstantValue *>(unaryValue);
        auto isConst = (constUnaryValue != nullptr);

        if (isConst)
        {
            // TODO: 缺少对i1转换
            switch (ctx->unaop->getText().c_str()[0])
            {
            case '+':
                return unaryValue;
                break;
            case '-':
                {
                    if (constUnaryValue->isFloat())
                    {
                        return (Value *)ConstantValue::get(-constUnaryValue->getFloat(),
                                                           to_hex(-constUnaryValue->getFloat()));
                    }
                    else
                    {
                        return (Value *)ConstantValue::get(-constUnaryValue->getInt(),
                                                           to_string(-constUnaryValue->getInt()), 32);
                    }
                }
                break;
            case '!':
                {
                    if (constUnaryValue->isFloat())
                    {
                        return (Value *)ConstantValue::get((int)!(constUnaryValue->getFloat()),
                                                           to_string((int)!(constUnaryValue->getFloat())), 32);
                    }
                    else
                    {
                        return (Value *)ConstantValue::get(!(constUnaryValue->getInt()),
                                                           to_string(!(constUnaryValue->getInt())), 32);
                    }
                }
                break;
            default:
                unimplemented("仅支持+-!三种一元运算符");
                break;
            }
        }

        else
        {
            switch (ctx->unaop->getText().c_str()[0])
            {
            case '+':
                {
                    if (unaryValue->isBool())
                    {
                        unaryValue = builder.createI1ToI32Inst(unaryValue, new_reg_name());
                    }
                    return unaryValue;
                }
                break;
            case '-':
                {
                    if (unaryValue->isBool())
                    {
                        unaryValue = builder.createI1ToI32Inst(unaryValue, new_reg_name());
                        return (Value *)builder.createNegInst(unaryValue, new_reg_name());
                    }
                    else if (unaryValue->isFloat())
                    {
                        return (Value *)builder.createFNegInst(unaryValue, new_reg_name());
                    }
                    else
                    {
                        return (Value *)builder.createNegInst(unaryValue, new_reg_name());
                    }
                }
                break;
            case '!':
                {
                    if (unaryValue->isFloat())
                    {
                        return (Value *)builder.createFCmpEQInst(unaryValue, ConstantValue::get(0.0f, to_hex(0.0)),
                                                                 new_reg_name());
                    }
                    else
                    {
                        return (Value *)builder.createNotInst(unaryValue, new_reg_name());
                    }
                }
                break;
            default:
                unimplemented("仅支持+-!三种一元运算符");
                break;
            }
        }
    }

    std::any SysYIRGenerator::visitMulUnaAsMul(SysYParser::MulUnaAsMulContext *ctx)
    {
        auto mulExp = any_cast<Value *>(ctx->mulExp()->accept(this));
        auto constMulExp = dynamic_cast<ConstantValue *>(mulExp);
        auto unaryExp = any_cast<Value *>(ctx->unaryExp()->accept(this));
        auto constUnaryExp = dynamic_cast<ConstantValue *>(unaryExp);
        auto mulOperator = ctx->mulop->getText();

        if (constMulExp && constUnaryExp)
        {
            // 两个均为常量, 则最终结果也是常量
            if (!constMulExp->isFloat() && !constUnaryExp->isFloat())
            {
                // 两个均不为float, 则不需要类型转换
                // 可能存在指针类型, 视为int
                // 除此之外所有情况都需要转换为float
                int mulV = constMulExp->getInt(), unaV = constUnaryExp->getInt();
                if (mulOperator == "*")
                {
                    return (Value *)ConstantValue::get(mulV * unaV, to_string(mulV * unaV), 32);
                }
                else if (mulOperator == "/")
                {
                    return (Value *)ConstantValue::get(mulV / unaV, to_string(mulV / unaV), 32);
                }
                else
                {
                    return (Value *)ConstantValue::get(mulV % unaV, to_string(mulV % unaV), 32);
                }
            }
            else
            {
                // 至少有任意一个是float, 则需要类型转换, 将非float转换为float
                // 可以用c++的自动转换
                float mulV, unaV;
                if (constMulExp->isInt())
                {
                    mulV = constMulExp->getInt();
                }
                else
                {
                    mulV = constMulExp->getFloat();
                }

                if (constUnaryExp->isInt())
                {
                    unaV = constUnaryExp->getInt();
                }
                else
                {
                    unaV = constUnaryExp->getFloat();
                }

                if (mulOperator == "*")
                {
                    return (Value *)ConstantValue::get(mulV * unaV, to_hex(mulV * unaV));
                }
                if (mulOperator == "/")
                {
                    return (Value *)ConstantValue::get(mulV / unaV, to_hex(mulV / unaV));
                }
                semantic_error("浮点数之间不能取模");
            }
        }
        else
        {
            if (!mulExp->isFloat() && !unaryExp->isFloat())
            {
                if (mulOperator == "*")
                {
                    return (Value *)builder.createMulInst(mulExp, unaryExp, new_reg_name());
                }
                else if (mulOperator == "/")
                {
                    return (Value *)builder.createDivInst(mulExp, unaryExp, new_reg_name());
                }
                else
                {
                    // ? 没有直接取余啊？
                    // unimplemented("没有直接取余指令, 似乎需要先除再乘再减");
                    return (Value *)builder.createRemInst(mulExp, unaryExp, new_reg_name());
                }
            }
            else
            {
                if (!mulExp->isFloat())
                {
                    mulExp = builder.createIToFInst(mulExp, new_reg_name());
                }

                if (!unaryExp->isFloat())
                {
                    unaryExp = builder.createIToFInst(unaryExp, new_reg_name());
                }

                if (mulOperator == "*")
                {
                    return (Value *)builder.createFMulInst(mulExp, unaryExp, new_reg_name());
                }
                if (mulOperator == "/")
                {
                    return (Value *)builder.createFDivInst(mulExp, unaryExp, new_reg_name());
                }
                unimplemented("没有直接取余指令, 似乎需要先除再乘再减");
            }
        }
        return nullptr;
    }

    std::any SysYIRGenerator::visitAddMulAsAdd(SysYParser::AddMulAsAddContext *ctx)
    {
        auto addExp = any_cast<Value *>(ctx->addExp()->accept(this));
        auto constAddExp = dynamic_cast<ConstantValue *>(addExp);
        auto mulExp = any_cast<Value *>(ctx->mulExp()->accept(this));
        auto constMulExp = dynamic_cast<ConstantValue *>(mulExp);
        auto addOp = ctx->addop->getText();

        if (constAddExp && constMulExp)
        {
            // 两个常量
            if (!constAddExp->isFloat() && !constMulExp->isFloat())
            {
                // 两个int
                int addV = constAddExp->getInt(), mulV = constMulExp->getInt();
                if (addOp == "+")
                {
                    return (Value *)ConstantValue::get(addV + mulV, to_string(addV + mulV), 32);
                }
                else
                {
                    return (Value *)ConstantValue::get(addV - mulV, to_string(addV - mulV), 32);
                }
            }
            else
            {
                float addV = constAddExp->getFloat(), mulV = constMulExp->getFloat();
                if (!constAddExp->isFloat())
                {
                    addV = constAddExp->getInt();
                }

                if (!constMulExp->isFloat())
                {
                    mulV = constMulExp->getInt();
                }

                if (addOp == "+")
                {
                    // TODO: float转换为llvmir可接受的准确浮点值作为名字
                    return (Value *)ConstantValue::get(addV + mulV, to_hex(addV + mulV));
                }
                else
                {
                    // TODO: float转换为llvmir可接受的准确浮点值作为名字
                    return (Value *)ConstantValue::get(addV - mulV, to_hex(addV - mulV));
                }
            }
        }
        else
        {
            if (!addExp->isFloat() && !mulExp->isFloat())
            {
                // 两个int
                if (addOp == "+")
                {
                    return (Value *)builder.createAddInst(addExp, mulExp, new_reg_name());
                }
                else
                {
                    return (Value *)builder.createSubInst(addExp, mulExp, new_reg_name());
                }
            }
            else
            {
                if (!addExp->isFloat())
                {
                    addExp = builder.createIToFInst(addExp, new_reg_name());
                }

                if (!mulExp->isFloat())
                {
                    mulExp = builder.createIToFInst(mulExp, new_reg_name());
                }

                if (addOp == "+")
                {
                    return (Value *)builder.createFAddInst(addExp, mulExp, new_reg_name());
                }
                else
                {
                    return (Value *)builder.createFSubInst(addExp, mulExp, new_reg_name());
                }
            }
        }
    }

    std::any SysYIRGenerator::visitLVal(SysYParser::LValContext *ctx)
    {
        // 语义
        // 左值: scalar -> 符号表中value(而非load), array -> GEPInst
        // 右值: scalar -> load, array element -> load, array name -> GEP 0
        auto name = ctx->Ident()->getText();
        auto val = scope.find(name);
        if (val == nullptr)
        {
            semantic_error(name + "未定义");
        }

        bool constDims = true;

        // 数组的索引(如果存在)一定是右值
        bool isPLV = builder.isPureLval;
        builder.isPureLval = false;
        vector<Value *> dims;
        for (auto exp : ctx->exp())
        {
            auto offset = any_cast<Value *>(exp->accept(this));
            if (!dynamic_cast<ConstantValue *>(offset))
            {
                constDims = false;
            }
            dims.push_back(offset);
        }
        builder.isPureLval = isPLV;

        Value *value = nullptr;

        if (auto gv = dynamic_cast<GlobalValue *>(val->value))
        {
            if (gv->isconst() && constDims)
            {
                // 常量作为左值是非法的
                // TODO: 但是万一有这种情况呢
                if (dims.empty())
                    value = gv->init();
                else if (gv->getType()->as<PointerType>()->getBaseType()->as<ArrayType>()->getBaseType()->isInt())
                {
                    value = ConstantValue::get(gv->getInt(dims), to_string(gv->getInt(dims)), 32);
                }
                else
                {
                    value = ConstantValue::get(gv->getFloat(dims), to_hex(gv->getFloat(dims)));
                }
            }
            else
            {
                value = gv;
                if (builder.isPureLval)
                {
                    if (!dims.empty())
                    {
                        value = builder.createGEPInst(gv, dims, new_reg_name());
                    }
                    else
                    {
                        value = gv;
                    }
                }
                else
                {
                    // 处理直接引用数组名
                    if (int num = gv->getNumDims(); num != 0)
                    {
                        // index不全, 说明引用的是一个指针, 只需GEP即可
                        if (num != dims.size())
                        {
                            for (auto _ = dims.size(); _ < num; _++)
                            {
                                dims.emplace_back(ConstantValue::get(0, "0", 32));
                            }

                            value = builder.createGEPInst(gv, dims, new_reg_name());
                        }
                        else
                        {
                            // index是全的, 则引用的是一个具体的标量值
                            value = builder.createGEPInst(gv, dims, new_reg_name());
                            value = builder.createLoadInst(value, new_reg_name());
                        }
                    }
                    else
                        value = builder.createLoadInst(value, new_reg_name());
                }
            }
        }
        else if (auto alloca = dynamic_cast<AllocaInst *>(val->value))
        {
            // TODO: alloca const?
            if (alloca->isconst())
            {
                if (alloca->getType()->as<PointerType>()->getBaseType()->as<ArrayType>()->getBaseType()->isInt())
                {
                    value = ConstantValue::get(alloca->getInt(dims), to_string(alloca->getInt(dims)), 32);
                }
                else
                {
                    value = ConstantValue::get(alloca->getFloat(dims), to_hex(alloca->getFloat(dims)), 32);
                }
            }
            else
            {
                if (!dims.empty())
                {
                    // dims非空, 则alloca一定不是scalar
                    // 1. 左值, 则需要拿到GEP; 且此时dims与数组维度一定符合, 否则语义错误
                    // 2. 右值, 在则需要先拿到GEP再load; 此时不一定符合

                    value = alloca;
                    auto pointedType = value->getType()->as<PointerType>()->getBaseType();
                    if (!(pointedType->isInt() || pointedType->isFloat() || pointedType->isArray()))
                    {
                        // 可能是针对嵌套的数组 a[b[114]]
                        value = builder.createLoadInst(value, new_reg_name());
                    }
                    value = builder.createGEPInst(value, dims, new_reg_name());
                }
                else
                {
                    // dims空, 则alloca可能是scalar也可能不是
                    // 1. 是scalar
                    // 1.1 左值, 则直接返回
                    // 1.2 右值, 则返回load
                    // 2. 非scalar
                    // 2.1 左值, 语义错误
                    // 2.2 右值, 把dims补0补全然后返回GEP
                    value = alloca;
                }
                // 到此为止, 左值的情况已经处理完了

                // 如果是右值
                if (!builder.isPureLval)
                    if (int num = alloca->getNumDims(); num != 0 && dims.size() != num)
                    {
                        vector<Value *> indices;
                        for (auto _ = dims.size(); _ < num; _++)
                        {
                            indices.emplace_back(ConstantValue::get(0, "0", 32));
                        }
                        // 笑点解析: 现在是dims不全的右值, 实际上dims是要补0的
                        // 更糟的是前面GEP已经创建过了, 怎么办呢?
                        // 对啦, 聪明的小朋友已经发现了我们的GEP参数里vector传的是非const引用
                        // 也就是说我可以再createGEP之后再去修改dims具体的值, 反正这个值到最后才会用
                        // 不觉得这很酷吗? 作为shit maker我觉得这太酷了, 很符合我对cpp的想象, 科技并带着趣味
                    }
                    else
                    {
                        // 右值scalar/右值数组且dims与数组维度符合, load后返回即可
                        value = builder.createLoadInst(value, new_reg_name());
                    }
            }
        }
        else if (auto arg = dynamic_cast<Argument *>(val->value))
        {
            // TODO: 基本块参数
            unimplemented("基本块参数");
        }
        else if (auto cv = dynamic_cast<ConstantValue *>(val->value))
        {
            value = val->value;
        }
        return value;
    }

    std::any SysYIRGenerator::visitLValAsPri(SysYParser::LValAsPriContext *ctx) { return ctx->lVal()->accept(this); }

    std::any SysYIRGenerator::visitExpAsPri(SysYParser::ExpAsPriContext *ctx) { return ctx->exp()->accept(this); }

    std::any SysYIRGenerator::visitLOrLAndAsLOr(SysYParser::LOrLAndAsLOrContext *ctx)
    {
        auto *CurBlock = builder.getBasicBlock(); // 当前块
        auto *Func = CurBlock->getParent(); // 当前函数

        stringstream or_name;
        or_name << "or_" << builder.getIfNum();
        auto *NewBlock = Func->addBasicBlock(or_name.str()); // TODO:NewBlock里加了个字符表,这里存在Phi函数（还没写）

        trueExit.push(trueExit.top());
        falseExit.push(NewBlock);
        ctx->lOrExp()->accept(this);
        builder.setPosition(NewBlock, NewBlock->begin());
        ctx->lAndExp()->accept(this);

        return (Value *)nullptr;
    }

    std::any SysYIRGenerator::visitLAndAsLOr(SysYParser::LAndAsLOrContext *ctx)
    {
        ctx->lAndExp()->accept(this);
        return (Value *)nullptr;
    }

    std::any SysYIRGenerator::visitLOrAsCond(SysYParser::LOrAsCondContext *ctx)
    {
        ctx->lOrExp()->accept(this);
        return (Value *)nullptr;
    }

    std::any SysYIRGenerator::visitStmtAssign(SysYParser::StmtAssignContext *ctx)
    {
        // TODO: 可能存在等号左右两边求值顺序的问题?
        // TODO: 具体语义还需考虑


        builder.isPureLval = true;
        // GEP if array / value if scalar
        auto lv = any_cast<Value *>(ctx->lVal()->accept(this));
        builder.isPureLval = false;


        auto rv = any_cast<Value *>(ctx->exp()->accept(this));
        auto lvBaseType = lv->getType()->as<PointerType>()->getBaseType();
        if (auto cv = dynamic_cast<ConstantValue *>(rv))
        {
            if (lvBaseType->isInt() && cv->isFloat())
            {
                rv = ConstantValue::get((int)cv->getFloat(), to_string((int)cv->getFloat()), 32);
            }
            else if (lvBaseType->isFloat() && cv->isInt())
            {
                rv = ConstantValue::get((float)cv->getInt(), to_string((float)cv->getInt()), 32);
            }
        }
        else if (lvBaseType->isInt() && rv->isFloat())
        {
            rv = builder.createFtoIInst(rv, new_reg_name());
        }
        else if (lvBaseType->isFloat() && rv->isInt())
        {
            rv = builder.createIToFInst(rv, new_reg_name());
        }


        builder.createStoreInst(rv, lv);
        return nullptr;
    }

    std::any SysYIRGenerator::visitStmtExp(SysYParser::StmtExpContext *ctx)
    {
        if (ctx->exp())
        {
            visitExp(ctx->exp());
        }
        return (Value *)nullptr;
    }

    std::any SysYIRGenerator::visitStmtReturn(SysYParser::StmtReturnContext *ctx)
    {
        // 将返回值(如存在)放到提前分配好的返回值alloca里
        Value *value = nullptr;
        auto *retType = builder.getBasicBlock()->getParent()->getReturnType();
        if (ctx->exp() != nullptr)
        {
            value = any_cast<Value *>(visitExp(ctx->exp()));
            if (value->isFloat() && !retType->isFloat())
                value = (Value *)builder.createFtoIInst(value, new_reg_name());
            else if (!value->isFloat() && retType->isFloat())
                value = (Value *)builder.createIToFInst(value, new_reg_name());
            // builder.createReturnInst(value, new_reg_name());
            auto retv = builder.getBasicBlock()->getParent()->getRetValue();
            builder.createStoreInst(value, retv);
        }

        auto currBlk = builder.getBasicBlock();
        auto funcExit = currBlk->getParent()->getFuncExitBlock();

        builder.createUncondBrInst(funcExit);
        currBlk->getSuccessors().emplace_back(funcExit);
        funcExit->getPredecessors().emplace_back(currBlk);

        return (Value *)nullptr;
    }

    std::any SysYIRGenerator::visitStmtIfElse(SysYParser::StmtIfElseContext *ctx)
    {
        bool urblw = builder.unreachableBelow;
        builder.unreachableBelow = false;


        builder.addIfNum();
        auto current_block = builder.getBasicBlock();
        auto func = current_block->getParent();
        stringstream then_name;
        then_name << "then_" << builder.getIfNum();
        auto then_block = func->addBasicBlock(then_name.str());

        if (ctx->stmt().size() == 1)
        {
            stringstream exit_name;
            exit_name << "if_exit_" << builder.getIfNum();
            auto *exit_block = func->addExitBlock(exit_name.str());

            trueExit.push(then_block);
            falseExit.push(exit_block);
            // 可能更改当前builder的基本块
            ctx->cond()->accept(this);

            builder.unreachableBelow = false;
            builder.setPosition(then_block, then_block->begin());
            ctx->stmt(0)->accept(this);
            current_block = builder.getBasicBlock();
            builder.unreachableBelow = false;


            Value *thenBr = builder.createUncondBrInst(exit_block);
            if (thenBr != nullptr)
            {
                current_block->getSuccessors().push_back(exit_block);
                exit_block->getPredecessors().push_back(current_block);
            }

            builder.setPosition(exit_block, exit_block->begin());
            func->moveExitBlock();
        }
        if (ctx->stmt().size() == 2)
        {
            stringstream else_name;
            else_name << "else_" << builder.getIfNum();
            auto else_block = func->addBasicBlock(else_name.str());

            stringstream exit_name;
            exit_name << "ifelse_exit_" << builder.getIfNum();
            auto *exit_block = func->addExitBlock(exit_name.str());
            trueExit.push(then_block);
            falseExit.push(else_block);
            ctx->cond()->accept(this);

            builder.unreachableBelow = false;
            builder.setPosition(then_block, then_block->begin());
            ctx->stmt(0)->accept(this);
            builder.unreachableBelow = false;

            current_block = builder.getBasicBlock();
            Value *thenBr = builder.createUncondBrInst(exit_block);
            if (thenBr != nullptr)
            {
                current_block->getSuccessors().push_back(exit_block);
                exit_block->getPredecessors().push_back(current_block);
            }

            builder.setPosition(else_block, else_block->begin());
            builder.unreachableBelow = false;
            ctx->stmt(1)->accept(this);
            builder.unreachableBelow = false;

            current_block = builder.getBasicBlock();
            Value *elseBr = builder.createUncondBrInst(exit_block);
            if (elseBr != nullptr)
            {
                current_block->getSuccessors().push_back(exit_block);
                exit_block->getPredecessors().push_back(current_block);
            }

            builder.setPosition(exit_block, exit_block->begin());
            func->moveExitBlock();
        }

        builder.unreachableBelow = urblw;
        return builder.getBasicBlock();
    }

    void getArrayPath(int num, const vector<int> &rdims, vector<int> &path)
    {
        for (int i = rdims.size() - 1; i >= 0; i--)
        {
            path[i] = num % rdims[i];
            num /= rdims[i];
        }
    }

    int getMaxSize(const int lowerBound, const int pos, const vector<int> &maxSize)
    {
        for (int i = lowerBound; i < maxSize.size(); i++)
        {
            if (pos % maxSize[i] == 0)
                return maxSize[i];
        }
        return -1;
    }

    std::any SysYIRGenerator::visitInitVal(SysYParser::InitValContext *ctx)
    {
        if (ctx->exp())
        {
            auto val = any_cast<Value *>(ctx->exp()->accept(this));
            if (builder.arrayInfo.onArray)
            {
                builder.arrayInfo.pos++;
                if (builder.arrayInfo.isAlloca)
                {
                    // alloca
                    vector<Value *> indices;
                    for (auto i : builder.arrayInfo.currentOffsets)
                    {
                        indices.emplace_back(ConstantValue::get(i, to_string(i), 32));
                    }
                    auto ptr = builder.createGEPInst(builder.arrayInfo.allocaValue, indices, new_reg_name());
                    builder.createStoreInst(val, ptr);

                    if (builder.arrayInfo.allocaValue->isconst() && dynamic_cast<ConstantValue *>(val))
                    {
                        if (val->isInt())
                            builder.arrayInfo.allocaValue->setInt(dynamic_cast<ConstantValue *>(val)->getInt(),
                                                                  indices);
                        else
                            builder.arrayInfo.allocaValue->setFloat(dynamic_cast<ConstantValue *>(val)->getFloat(),
                                                                    indices);
                    }
                }
                else
                {
                    // global; const init values;

                    if (val->isInt())
                    {
                        builder.arrayInfo.globalValue->setInt(dynamic_cast<ConstantValue *>(val)->getInt(),
                                                              builder.arrayInfo.currentOffsets);
                    }
                    else
                    {
                        builder.arrayInfo.globalValue->setFloat(dynamic_cast<ConstantValue *>(val)->getFloat(),
                                                                builder.arrayInfo.currentOffsets);
                    }
                }
            }

            return val;
        }
        else
        {
            // array
            // ref: https://blog.csdn.net/weixin_56462041/article/details/128908399
            // 假设不存在使用{scalar}初始化scalar initializer的情况(clang -Wbraced-scalar-init)
            builder.arrayInfo.maxSizeLowerBound++;
            auto maxSize =
                getMaxSize(builder.arrayInfo.maxSizeLowerBound, builder.arrayInfo.pos, builder.arrayInfo.maxSize);
            const auto endPos = builder.arrayInfo.pos + maxSize;


            for (auto init : ctx->initVal())
            {
                init->accept(this);
                getArrayPath(builder.arrayInfo.pos, builder.arrayInfo.realDims, builder.arrayInfo.currentOffsets);
            }

            // 空余位置补0
            // 假如提前用memset设置全0, 是否可以忽略这部分?
            // while (builder.arrayInfo.pos < endPos)
            // {
            //     if (builder.arrayInfo.isAlloca)
            //     {
            //         vector<Value *> indices;
            //         for (const auto dim : builder.arrayInfo.currentOffsets)
            //         {
            //             indices.emplace_back(ConstantValue::get(dim, to_string(dim)));
            //         }
            //         GEPInst *ptr = builder.createGEPInst(builder.arrayInfo.allocaValue, indices, new_reg_name());
            //
            //
            //         if (builder.arrayInfo.allocaValue->getType()->as<PointerType>()->getBaseType()->isInt())
            //         {
            //             builder.createStoreInst(ConstantValue::get(0, to_string(0)), ptr);
            //         }
            //         else
            //         {
            //             builder.createStoreInst(ConstantValue::get(0.0f, to_hex(0.0f)), ptr);
            //         }
            //     }
            //
            //     builder.arrayInfo.pos++;
            //     getArrayPath(builder.arrayInfo.pos, builder.arrayInfo.realDims, builder.arrayInfo.currentOffsets);
            //
            // }

            builder.arrayInfo.pos = endPos;

            builder.arrayInfo.maxSizeLowerBound--;
        }
        return nullptr;
    }

    std::any SysYIRGenerator::visitStmtWhile(SysYParser::StmtWhileContext *ctx)
    {
        bool urblw = builder.unreachableBelow;
        builder.unreachableBelow = false;

        builder.addWhileNum();
        auto *curBlock = builder.getBasicBlock(); // 当前所在基本块
        auto *func = curBlock->getParent(); // 当前所在函数

        // TODO:缺少phi函数
        stringstream while_cond_name;
        while_cond_name << "while_cond_" << builder.getWhileNum();
        auto *entryBlock = func->addBasicBlock(while_cond_name.str()); // 循环入口
        stringstream while_body_name;
        while_body_name << "while_body_" << builder.getWhileNum();
        auto *bodyBlock = func->addBasicBlock(while_body_name.str()); // 循环体
        stringstream while_exit_name;
        while_exit_name << "while_exit_" << builder.getWhileNum();
        auto *exitBlock = func->addExitBlock(while_exit_name.str()); // 结束部分

        auto ins = builder.createUncondBrInst(entryBlock);
        if (ins != nullptr)
        {
            entryBlock->getPredecessors().push_back(curBlock);
            curBlock->getSuccessors().push_back(entryBlock);
        }

        // 处理while_cond块
        builder.setPosition(entryBlock, entryBlock->begin());
        trueExit.push(bodyBlock);
        falseExit.push(exitBlock);
        ctx->cond()->accept(this);
        builder.unreachableBelow = false;

        // 处理while_body块
        builder.setPosition(bodyBlock, bodyBlock->begin());
        loopEntry.push_back(entryBlock);
        loopExit.push_back(exitBlock);
        ctx->stmt()->accept(this);
        builder.unreachableBelow = false;

        loopExit.pop_back();
        loopEntry.pop_back();
        curBlock = builder.getBasicBlock();

        ins = builder.createUncondBrInst(entryBlock);
        if (ins != nullptr)
        {
            entryBlock->getPredecessors().push_back(curBlock);
            curBlock->getSuccessors().push_back(entryBlock);
        }

        builder.setPosition(exitBlock, exitBlock->begin());
        func->moveExitBlock();

        builder.unreachableBelow = urblw;

        return nullptr;
    }

    std::any SysYIRGenerator::visitStmtBreak(SysYParser::StmtBreakContext *ctx)
    {
        auto ins = builder.createUncondBrInst(loopExit.back());
        if (ins != nullptr)
        {
            builder.getBasicBlock()->getSuccessors().push_back(loopExit.back());
            loopExit.back()->getPredecessors().push_back(builder.getBasicBlock());
        }
        return (Value *)nullptr;
    }

    std::any SysYIRGenerator::visitStmtContinue(SysYParser::StmtContinueContext *ctx)
    {
        auto ins = builder.createUncondBrInst(loopEntry.back());
        if (ins != nullptr)
        {
            builder.getBasicBlock()->getSuccessors().push_back(loopEntry.back());
            loopEntry.back()->getPredecessors().push_back(builder.getBasicBlock());
        }
        return (Value *)nullptr;
    }

    std::any SysYIRGenerator::visitFuncCallAsUna(SysYParser::FuncCallAsUnaContext *ctx)
    {
        auto func = dynamic_cast<Function *>(scope.find(ctx->Ident()->toString())->value);
        if (!func)
        {
            semantic_error("函数" + ctx->Ident()->getText() + "未定义");
        }
        vector<Value *> args;
        if (ctx->funcRParams())
        {
            for (auto i = 0; i < func->getParamTypes().size(); i++)
            {
                auto arg = any_cast<Value *>(ctx->funcRParams()->exp(i)->accept(this));
                auto expectedType = func->getParamTypes()[i];

                if (auto cv = dynamic_cast<ConstantValue *>(arg))
                {
                    if (expectedType->isInt() && cv->isFloat())
                    {
                        arg = ConstantValue::get((int)cv->getFloat(), to_string((int)cv->getFloat()), 32);
                    }
                    else if (expectedType->isFloat() && cv->isInt())
                    {
                        arg = ConstantValue::get((float)cv->getInt(), to_hex((float)cv->getInt()));
                    }
                }
                else if (expectedType->isInt() && arg->isFloat())
                {
                    arg = builder.createFtoIInst(arg, new_reg_name());
                }
                else if (expectedType->isFloat() && arg->isInt())
                {
                    arg = builder.createIToFInst(arg, new_reg_name());
                }

                args.push_back(arg);
            }
        }
        return (Value *)builder.createCallInst(func, args, new_reg_name());
    }
} // namespace sysy
